﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.IO;

namespace SimpleInfrastructure.Log
{
    public class FileLogger:ILogger
    {
        private FileLogger()
        {
            
        }
        static FileLogger()
        {
            Task t = new Task(ExcuteWrite);
            _today = DateTime.Now.Date;
            _logFileName = string.Format(@"{0}\{1}.log.txt", AppDomain.CurrentDomain.BaseDirectory, _today.ToString("yyyyMMdd"));
            t.Start();
            _logger = new FileLogger();
        }
        static DateTime _today;
        static string _logFileName;

        static readonly Queue<string> Errors = new Queue<string>();

        static readonly object LogLock = new object();

        private static readonly FileLogger _logger;

        public static FileLogger Instance
        {
            get { return _logger; }
        }

        private static void ExcuteWrite()
        {
            while (true)
            {
                try
                {
                    if (Errors != null && Errors.Count > 0)
                    {
                        string errorLogInfo = String.Empty;
                        lock (LogLock)
                        {
                            errorLogInfo = Errors.Dequeue();
                        }
                        DateTime dt = DateTime.Now.Date;
                        if (dt != _today)
                        {
                            _today = dt;
                            _logFileName = string.Format(@"{0}\{1}.log.txt",
                                AppDomain.CurrentDomain.BaseDirectory, _today.ToString("yyyyMMdd"));
                        }
                        if (!string.IsNullOrEmpty(errorLogInfo))
                        {
                            File.AppendAllText(_logFileName, errorLogInfo);
                        }
                    }
                    else
                    {
                        Thread.Sleep(500);
                    }
                }
                catch
                {

                }
            }
        }

        public bool IsEnabled(LogLevel level)
        {
            return true;
        }

        public void Log(LogLevel level, Exception exception, string messageFormat, params object[] args)
        {
            StringBuilder sb = new StringBuilder();
            var ex = exception.GetBaseException();
            string dt = DateTime.Now.ToString();
            sb.Append(dt)
                .Append(System.Environment.NewLine + level.ToString()+":").Append(string.Format(messageFormat, args))
                .Append(System.Environment.NewLine + "错误消息:").Append(ex.Message ?? "")
                .Append(System.Environment.NewLine + "堆栈:").Append(ex.StackTrace ?? "")
                .Append(System.Environment.NewLine);
            lock (LogLock)
            {
                Errors.Enqueue(sb.ToString());
            }
        }

        public void Log(LogLevel level, string messageFormat, params object[] args)
        {
            StringBuilder sb = new StringBuilder();
            string dt = DateTime.Now.ToString();
            sb.Append(dt)
                .Append(System.Environment.NewLine + level.ToString() + ":").Append(string.Format(messageFormat, args))
                .Append(System.Environment.NewLine);
            lock (LogLock)
            {
                Errors.Enqueue(sb.ToString());
            }
        }
    }
}
